package main

import (
	"fmt"
	"io/ioutil"
	"log"
        "net/http"
	"os"
	"os/signal"
	"syscall"
        "flag"
	"gopkg.in/mgo.v2"
        //"gopkg.in/mgo.v2/bson"
        "encoding/json"
        "minio-webhook-mongodb/goutils"
        "minio-webhook-mongodb/entity"
        "minio-webhook-mongodb/setting"
        "minio-webhook-mongodb/logging"
)



//AppVersion version
var (
    vers *bool
    help *bool
    version   = "1.0.0"
    gitHash   = ""
    buildTime = "2022-08-23"

    conf string
    port string
    authToken string
    storetype string
       
)

func init(){
    vers = flag.Bool("v", false, "display the version.")
    help = flag.Bool("h", false, "print this help.")
    flag.StringVar(&conf,"c","app.ini","special configure file")
    flag.Parse()

    if *vers {
        fmt.Println("Version:", version)
        fmt.Println("Git Commit Hash:", gitHash)
        fmt.Println("UTC Build Time:", buildTime)
        os.Exit(0)
    }

    if *help {
        flag.Usage()
        os.Exit(0)
    }

  setting.Setup(conf)
  logging.Setup( logging.Level(setting.GlobalSetting.LogLevel))
}


func main() {
    port = setting.GlobalSetting.Port
    authToken = setting.GlobalSetting.Token
    storetype = setting.GlobalSetting.StoreType

    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGHUP,syscall.SIGINT,syscall.SIGKILL,syscall.SIGTERM,syscall.SIGSTOP,syscall.SIGUSR1,syscall.SIGUSR2)
    logging.Debug("Prepare to catch abnormal interrupt like Ctrl+C/Kill with signal")
    go func() {
        for s := range sigs {
            //logging.Error("Exit By Abnormal Signal:", s)
            switch s {
            case syscall.SIGHUP,syscall.SIGTERM,syscall.SIGQUIT,syscall.SIGINT,syscall.SIGSTOP :
                fmt.Println("Exit by Signal :",s)
                logging.Error("Exit By Abnormal Signal: ",s)
                os.Exit(0)
            default :
                fmt.Println("other signal" ,s)
                logging.Error("Exit By Abnormal Signal:",s)
            }
        }
    }()
    
    logging.Info("Conneting to MongoDB ",setting.MogdbSetting.DbUrl)

    session, err := mgo.Dial(setting.MogdbSetting.DbUrl)
    if err != nil {
        logging.Error("Connect Mongodb Fail:",err)
        os.Exit(0)
    }
    defer session.Close()
    session.SetPoolLimit(10)
    session.SetMode(mgo.Monotonic, true)
    //err =  session.Login("root","root")
    logging.Debug("Username:",setting.MogdbSetting.DbUser)
    logging.Debug("Password:",setting.MogdbSetting.DbPassword)
    logging.Debug("AuthDB:",setting.MogdbSetting.DbAuthdb)
    logging.Debug("DbName:",setting.MogdbSetting.DbName)

    err =  session.DB(setting.MogdbSetting.DbAuthdb).Login(setting.MogdbSetting.DbUser,setting.MogdbSetting.DbPassword)
        if err != nil {
          logging.Error("Login Mongodb Fail using configfile :",err)
          os.Exit(0)
        }
        logging.Info("Connected to MongoDB") 
        c := session.DB(setting.MogdbSetting.DbName).C("miniolog")

        var miniolog entity.Miniolog
        //var api entity.Api
        logging.Info("Listening on port :",port)
	err = http.ListenAndServe(":"+port, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if authToken != "" {
			if authToken != r.Header.Get("Authorization") {
                            logging.Error("Token does not match config setting")
		            return
			}
		}
                localhost := goutils.GetIP(r)
                logging.Debug("Server IP:",localhost)

		switch r.Method {
		case "POST":
			data, err := ioutil.ReadAll(r.Body)
			if err != nil {
				return
			}

                        //var miniolog Miniolog
        		err2 := json.Unmarshal([]byte(data), &miniolog)
        		if err2 != nil {
          			panic(err)
        		}
                        logging.Debug("Had Unmarshaled JSON to Miniolog struct")
                        if setting.MogdbSetting.SaveAllField == "1" {
                            logging.Debug("Inserting full JSON to miniolog collection")
                            miniolog.API.Localhost = localhost
                            err = c.Insert(&miniolog)
                            //miniolog = entity.Miniolog{} //Set miniolog null
                        }else {
                            //var api entry.Api
                            api := miniolog.API
                            api.Localhost = localhost
                            api.Time = miniolog.Time
                            api.Remotehost = miniolog.Remotehost
                            logging.Debug("Inserting JSON 'API Section' to miniolog collection")
                            err = c.Insert(&api)
                            //api = entity.Api{}
                        }
        		if err != nil {
                           log.Fatal(err)
        		}
		default:
		}
	}))
	if err != nil {
		log.Fatal(err)
	}
}
